home *** CD-ROM | disk | FTP | other *** search
/ Amiga Game-Power / Amiga Game-Power.iso / anwendungen / d mouse / calls / main.c < prev    next >
C/C++ Source or Header  |  1994-05-20  |  8KB  |  323 lines

  1. /*
  2.  * main.c -- calls mainline, trace calling sequences of C programs
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <errno.h>
  8.  
  9. #include "debug.h"
  10.  
  11. #ifdef MCH_AMIGA
  12. extern int strlen();
  13. extern char *malloc();
  14. #else
  15. #include <strings.h>
  16. #endif
  17.  
  18. #include "scan.h"
  19. #include "getopt.h"
  20. #include "main.h"
  21.  
  22. /* globals */
  23.  
  24. int debug=0;
  25.  
  26. char
  27.     sbCmd[] = "cmd line";    /* kludge to notify user of error    */
  28. int
  29.     Allp = 0,        /* flag to show *all* function calls    */
  30.     Tersep = 0,        /* only requested trees            */
  31.     Externp = 0,        /* include externs in index        */
  32.     Indexp = 0,        /* output functions index        */
  33.     Verbosep = 1;        /* index functions not output        */
  34.  
  35. /* locals */
  36. static int
  37.     linect = 0,        /* line number                */
  38.     activep = 0,        /* current function being output    */
  39.     iWidth = PAPERWIDTH;    /* default paper width            */
  40. static char
  41.     *pchProg,        /* argv[0]                */
  42.     cppcommand[1024] =    /* cpp command string            */
  43.         "/lib/cpp -P ";
  44. static HASH
  45.     *activelist[MAXDEPTH];    /* list of current output names        */
  46.  
  47.  
  48. char *
  49. syserrlist()    /*  the routine returns a string for a system error    */
  50. {
  51.     extern char *sys_errlist[];
  52.     extern int sys_nerr;
  53.     extern int errno;
  54.     register char *pchErr =
  55.         errno == 0 ? "errno = 0" :
  56.         errno < sys_nerr ? sys_errlist[errno] : "errno out of range";
  57.  
  58.     errno = 0;
  59.     return pchErr;
  60. }
  61.  
  62. void
  63. process(filename, outname)    /* invoke cpp on file, call level1    */
  64. register char *filename, *outname;
  65. {
  66.     extern FILE *popen();
  67.     extern FILE *fopen();
  68.     register char *sbNull;
  69.     register int ret;
  70.  
  71. DEBUG1(3, "process entered: with file [%s]\n", filename);
  72.  
  73. #ifdef MCH_AMIGA    /* Can't find a way to pre-process files with Manx */
  74.  
  75.     if ((input = fopen(filename, "r")) == EOF )
  76.     {
  77.         (void) fprintf(stderr, "%s: cannot open file '%s' (%s).\n", pchProg, filename, syserrlist());
  78.     }
  79.     else
  80.         level1(filename);    /* Just process file as is for now */
  81. #else
  82.  
  83.     if (access(filename, 04) != 0) {
  84.         (void) fprintf(stderr, "%s: cannot open file '%s' (%s).\n", pchProg, filename, syserrlist());
  85.         return;
  86.     }
  87.     sbNull = cppcommand + strlen(cppcommand);
  88.     strcpy(sbNull, filename);
  89.  
  90.     if (NULL == (input = popen(cppcommand, "r"))) {
  91.         (void) fprintf(stderr, "%s: fork of CPP command '%s' failed on file '%s' (%s).\n", pchProg, cppcommand, filename, syserrlist());
  92.     } else {
  93.         level1(outname);
  94.         if (0 != (ret = pclose(input)))
  95.             (void) fprintf(stderr, "%s: CPP command '%s' failed on file '%s' with return code %d.\n", pchProg, cppcommand, filename, ret);
  96.     }
  97.  
  98. #endif
  99.  
  100.     *sbNull = '\0';
  101.     return;
  102. }
  103.  
  104. void
  105. dostdin()    /* copy stdin to temp file, call process on file    */
  106. {
  107.     extern char *mktemp();
  108.     register int cc;
  109.     register char *filename = mktemp("/tmp/callsXXXXXX");
  110.     register FILE *ofileptr = fopen(filename, "w");
  111.     register char *sbNull;
  112.  
  113.     if (NULL == ofileptr) {
  114.         (void) fprintf(stderr, "%s: cannot open tempfile '%s' for writing (%s).\n", pchProg, filename, syserrlist());
  115.     } else {
  116.         while (EOF != (cc = getchar()))
  117.             putc(cc, ofileptr);
  118.         fclose(ofileptr);
  119.         sbNull = cppcommand + strlen(cppcommand);
  120.         strcpy(sbNull, "-I. ");
  121.         process(filename, "stdin");
  122.         *sbNull = '\000';
  123.         unlink(filename);
  124.     }
  125. }
  126.  
  127. int
  128. active(func)    /* check for recursive calls, prevents endless output    */
  129. register HASH *func;
  130. {
  131.     register int i;
  132.  
  133.     for (i = 0; i < activep-1; i++)
  134.         if (func == activelist[i])
  135.             return 1;
  136.     return 0;
  137. }
  138.  
  139. void
  140. output(pHTFunc, tabc)    /* output a (sub)tree in pretty form        */
  141. register HASH *pHTFunc;
  142. register int tabc;
  143. {
  144.     static char dashes[] = "\n----------";
  145.     register INST *pINTemp;
  146.     register int i;
  147.  
  148.     ++linect;
  149.     (void) printf("\n%5d\t", linect);
  150.     if (activep < MAXDEPTH) {
  151.         activelist[activep++] = pHTFunc;
  152.     } else {
  153.         (void) printf("   * nesting is too deep");
  154.         return;
  155.     }
  156.  
  157.     for (i = 0; i < tabc; i++ )
  158.         putchar('\t');
  159.     printf("%s", pHTFunc->pchname);
  160.  
  161.     if (active(pHTFunc)) {
  162.         (void) printf(" <<< recursive >>>");
  163.     } else if (pHTFunc->pchfile) {
  164.         pINTemp = pHTFunc->pINcalls;
  165.         if (pHTFunc->listp && tabc && 0 == pHTFunc->iline) {
  166.             (void) printf(" [%s] [see below]", pHTFunc->pchfile);
  167.         } else if (! pHTFunc->iline) {
  168.             (void) printf(pHTFunc->localp ? " [static in %s]" : " [%s]", pHTFunc->pchfile);
  169.             pHTFunc->iline = linect;
  170.             if ((++tabc) * TABWIDTH >= iWidth) {
  171.                 (void) printf(dashes);
  172.                 tabc = 0;
  173.             }
  174.             while (pINTemp) {
  175.                 output(pINTemp->pHTname, tabc);
  176.                 pINTemp = pINTemp->pINnext;
  177.             }
  178.             if (! tabc)
  179.                 (void) printf(dashes);
  180.         } else if (pINTemp || pHTFunc->localp) {
  181.             (void) printf(" [see line %d]", pHTFunc->iline);
  182.         }
  183.     }
  184.     activelist[activep--] = nilHASH;
  185. }
  186.  
  187. int
  188. main(argc, argv)    /* parse args, add files, call output        */
  189. int argc;
  190. char *argv[];
  191. {
  192.     extern int atoi();
  193.     extern char *index();
  194.     static char sbOpts[] = "aehitvw:x:D:f:F:U:I:"; /* valid options    */
  195.     static char sbTemp[200];
  196.     static LIST *pCLRoot;
  197.     register HASH *pHTList;
  198.     register int cOption;
  199.     register LIST **ppCL;
  200.     register char *pchSplit;
  201.  
  202.     pchProg = argv[0];
  203.     ppCL = & pCLRoot;
  204.  
  205.     while (EOF != (cOption = getopt(argc, argv, sbOpts))) {
  206.         switch (cOption) {
  207.         case 'a':
  208.             Allp = 1;
  209.             break;
  210.         case 'x':
  211.             debug = atoi(optarg);
  212.             break;
  213.         case 'e':
  214.             Externp = 1;
  215.             Indexp = 1;
  216.             break;
  217.         case 'F':
  218.             if (0 != (pchSplit = index(optarg, '/'))) {
  219.                 *pchSplit++ = '\000';
  220.             } else {
  221.         case 'f':    
  222.                 pchSplit = sbCmd;
  223.             }
  224.             pHTList = search(optarg, 'F' == cOption, pchSplit);
  225.             pHTList->listp = 1;
  226.             pHTList->pchfile = pchSplit;
  227.             *ppCL = (LIST *) malloc( sizeof(LIST) ) ;
  228.             (*ppCL)->pCLnext = pCLRoot;
  229.             (*ppCL)->pHTlist = pHTList;
  230.             ppCL = & (*ppCL)->pCLnext;
  231.             break;
  232.         case 't':    
  233.             Tersep = 1;
  234.             break;
  235.         case 'v':
  236.             Verbosep = 0;
  237.             /*fallthrough*/
  238.         case 'i':
  239.             Indexp = 1;
  240.             break;
  241.         case 'w':
  242.             if (0 >= (iWidth = atoi(optarg)))
  243.                 iWidth = PAPERWIDTH;
  244.             break;
  245.         case 'D':
  246.         case 'I':
  247.         case 'U':
  248.             sprintf(sbTemp, "-%c%s ", cOption, optarg);
  249.             strcat(cppcommand, sbTemp);
  250.             break;
  251.         case '?':
  252.         case 'h':
  253.             (void) fprintf(stderr, "usage: %s [-aehitv] [-f function] [-F function[/file.c]] [-w width]\n\
  254.     [-D define] [-U undefine] [-I include-dir] [filename|-]*\n\
  255. \ta\tprint all calls in every function body\n\
  256. \te\tindex external functions too\n\
  257. \tf,F\tstart calling trace at given function\n\
  258. \th\tprint this message\n\
  259. \ti\tprint an index of defined functions\n\
  260. \tv\tlist only called functions in index output\n\
  261. \tt\tterse, list only trees that are requested\n\
  262. \tw\tset ouptut width\n\
  263. \tD,U,I\tas in cpp\n", pchProg);
  264.             exit('h' != cOption);
  265.         }
  266.     }
  267.     *ppCL = nilCL;
  268.  
  269.     while (EOF != getarg(argc, argv)) {
  270.         if ('-' == optarg[0] && '\000' == optarg[1])
  271.             dostdin();
  272.         else
  273.             process(optarg, optarg);
  274.     }
  275.  
  276.     while (pCLRoot) {        /* print requested trees    */
  277.         output(pCLRoot->pHTlist, 0);
  278.         putchar('\n');
  279.         pCLRoot = pCLRoot->pCLnext;
  280.     }
  281.  
  282.     if (!Tersep) {            /* print other trees        */
  283.         for (cOption = 0; cOption < 2; ++cOption) {
  284.             for (pHTList = pHTRoot[cOption]; pHTList; pHTList = pHTList->pHTnext) {
  285.                 if (!pHTList->calledp && NULL != pHTList->pchfile) {
  286.                     output(pHTList, 0);
  287.                     putchar('\n');
  288.                 }
  289.             }
  290.         }
  291.     }
  292.  
  293.     if (Indexp) {            /* print index            */
  294.         printf("\fIndex:\n");
  295.         while (nilHASH != pHTRoot[0] || nilHASH != pHTRoot[1]) {
  296.             
  297.             if (nilHASH == pHTRoot[0] || (nilHASH != pHTRoot[1] && strcmp(pHTRoot[0]->pchname, pHTRoot[1]->pchname) >= 0)) {
  298.                 pHTList = pHTRoot[1];
  299.                 pHTRoot[1] = pHTRoot[1]->pHTnext;
  300.             } else {
  301.                 pHTList = pHTRoot[0];
  302.                 pHTRoot[0] = pHTRoot[0]->pHTnext;
  303.             }
  304.             if (!Externp && NULL == pHTList->pchfile)
  305.                 continue;
  306.             if (!Verbosep && 0 == pHTList->iline)
  307.                 continue;
  308.             putchar('\t');
  309.             fputs(pHTList->pchname, stdout);
  310.             if (pHTList->localp) {
  311.                 printf(" [static in %s]", pHTList->pchfile);
  312.             } else if (((char *) 0) != pHTList->pchfile) {
  313.                 printf(" [%s]", pHTList->pchfile);
  314.             }
  315.             if (0 != pHTList->iline) {
  316.                 printf(" [see line %d]", pHTList->iline);
  317.             }
  318.             putchar('\n');
  319.         }
  320.     }
  321.     exit(0);
  322. }
  323.